#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <fstream>
#include <windows.h>
#include<cstring>
using namespace std;
class Date
{
private:
    int year;
    int month;
    int day;

public:
    Date(int y = 0, int m = 0, int d = 0)
    {
        year = y;
        month = m;
        day = d;
    }
    int Getday()
    {
        return day;
    }
    int Getmonth()
    {
        return month;
    }
    int Getyear()
    {
        return year;
    }
    void Reset(int y, int m, int d)
    {
        year = y;
        month = m;
        day = d;
    }
    friend ostream& operator<<(ostream& os, const Date& d)
    {
        os << d.year << "-" << d.month << "-" << d.day << endl;
        return os;
    }
};
class Person
{
protected:
    string name;
    int sex;
    Date birthday;

public:
    Person(string n, int s, int y, int m, int d) : birthday(y, m, d), name(n), sex(s) {}
    Person()
    {
        sex=0;
        birthday = Date(0, 0, 0);
    }
    string Getname()
    {
        return name;
    }
    int Getsex()
    {
        return sex;
    }
    int Getyear()
    {
        return birthday.Getyear();
    }
    int Getmonth()
    {
        return birthday.Getmonth();
    }
    int Getday()
    {
        return birthday.Getday();
    }
    void ResetP(string na, int se, int y, int m, int d)
    {
        name = na;
        sex = se;
        birthday.Reset(y, m, d);
    }
    friend ostream& operator<<(ostream& os, const Person& p)
    {
        os << "姓名:" << p.name << endl;
        if (p.sex == 1)
            os << "性别:男" << endl;
        else
            os << "性别:女" << endl;
        os << "生日:";
        os << p.birthday;
        return os;
    }
};
class Node : public Person
{
private:
    Person* P2;
    Node* parent;
    Node* left;
    Node* right;

public:
    Node(Node* p = NULL, Node* l = NULL, Node* r = NULL) : parent(p), left(l), right(r)
    {
        P2 = NULL;
    }
    Node(string n, int s, int y, int m, int d) : Person(n, s, y, m, d), parent(NULL), left(NULL), right(NULL)
    {
        P2=NULL;
    }
    ~Node()
    {
        // delete P1;
        delete P2;
    }
    string Getbirthday()
    {
        string s;
        s += to_string(Getyear());
        s += "-";
        s += to_string(Getmonth());
        s += "-";
        s += to_string(Getday());
        return s;
    }
    string GetP2birthday()
    {
        string s;
        s += to_string(P2->Getyear());
        s += "-";
        s += to_string(P2->Getmonth());
        s += "-";
        s += to_string(P2->Getday());
        return s;
    }
    Person* GetP2()
    {
        if(P2==NULL)
            return NULL;
        return P2;
    }
    void ResetP2(string nn,int ss,int yy,int mm,int dd )
    {
        if(P2==NULL)
            P2=new Person(nn,ss,yy,mm,dd);
        else
            P2->ResetP(nn,ss,yy,mm,dd);
    }
    friend ostream& operator<<(ostream& os, const Node& n)
    {
        os << "个人信息:" << endl;
        os << "姓名:" << n.name << endl;
        if (n.sex == 1)
            os << "性别:男" << endl;
        else
            os << "性别:女" << endl;
        os << "生日:";
        os << n.birthday;
        if (n.P2 != NULL)
            os << "配偶信息:" << endl
               << *(n.P2) << endl;
        else
            os << "无配偶信息" << endl;
        return os;
    }
    bool operator==(const Node& n)
    {
        return name == n.name;
    }
    Node* find(string name)
    {
        if (this->name == name)
            return this;
        if (left != NULL)
        {
            Node* temp = left->find(name);
            if (temp != NULL)
                return temp;
        }
        if (right != NULL)
        {
            Node* temp = right->find(name);
            if (temp != NULL)
                return temp;
        }
        return NULL;
    }
    void SetP2(Person* p)
    {
        P2 = p;
    }
    void Rename(string s)
    {
        name = s;
    }
    Node* Getleft()
    {
        return left;
    }
    void Setleft(Node* l)
    {
        left = l;
    }
    Node* Getright()
    {
        return right;
    }
    void Setright(Node* r)
    {
        right = r;
    }
    void Setparent(Node* p)
    {
        parent = p;
    }
    string Getname()
    {
        return name;
    }
    Node* Getparent()
    {
        for (Node* p = this; p != NULL; p = p->parent)
        {
            if (p->parent == NULL)
                continue;
            if (p->parent->left == p)
                return p->parent;
        }
        return NULL;
    }
    void addbrother(Node* temp, Person* tp = NULL)
    {
        temp->SetP2(tp);
        //cout << "请输入兄弟信息:" << endl;
        for (Node* p = this; p != NULL; p = p->right)
        {
            if (p->right == NULL)
            {
                p->right = temp;
                temp->parent = p;
                break;
            }
        }
    }
    void addchild(Node* temp, Person* tp = NULL)
    {
        temp->SetP2(tp);
        //cout << "请输入子女信息:" << endl;
        if (left == NULL)
        {
            left = temp;
            temp->parent = this;
        }
        else
        {
            left->addbrother(temp, tp);
        }
    }
    vector<Node*>* displaybrother(vector<Node*>* v)
    {
        //cout << "兄弟信息:" << endl;
        Node* p = Getparent();
        if (p == NULL)
        {
            p = this;
            while (p->parent != NULL)
                p = p->parent;
        }
        else
            p = p->left;
        for (; p != NULL; p = p->right)
        {
            v->push_back(p);
        }
        return v;
    }
    vector<Node*>* displaychild(vector<Node*>* v)
    {
        if (left == NULL) {}
        //cout << "无子女信息" << endl;
        else
        {
            //cout << "子女信息:" << endl;
            for (Node* p = left; p != NULL; p = p->right)
            {
                v->push_back(p);
            }
        }
        return v;
    }
    int Calgen()
    {
        int count = 0;
        for (Node* p = this; p != NULL; p = p->parent)
        {
            if (p->parent == NULL)
                continue;
            if (p->parent->left == p)
                count++;
        }
        return count;
    }
    void travel(vector<Node*>* v)
    {
        v->push_back(this);
        if(left!=NULL)  left->travel(v);
        if(right!=NULL) right->travel(v);
    }
    void travel1(vector<Node*>* v,int x)
    {
        (*v)[x]=this;
        if(left!=NULL)  left->travel1(v,x*2);
        if(right!=NULL) right->travel1(v,x*2+1);
    }
    int maxDepth(Node* root) {
        if (root == nullptr) {
            return 0; // 空树的深度为0
        }
        // 递归计算左子树和右子树的深度
        int leftDepth = maxDepth(root->left);
        int rightDepth = maxDepth(root->right);

        // 返回最大深度
        return max(leftDepth, rightDepth) + 1;
    }
};
class BTFG
{
private:
    Node* root;

public:
    BTFG()
    {
        //cout << "请根据提示创建最上级人物" << endl;
        root = new Node(NULL, NULL, NULL);
    }
    BTFG(string path)
    {
        root = NULL;
        ifstream in(path);
        int n, m;
        in >> n >> m;
        vector<int> v[3];
        vector<Node*> vv;
        for (int i = 1; i <= m; i++)
        {
            int a, b, c;
            in >> a >> b >> c;
            v[0].push_back(a);
            v[1].push_back(b);
            v[2].push_back(c);
        }
        vv.push_back(NULL);
        for (int i = 1; i <= n; i++)
        {
            string name;
            int sex, y, m, d;
            in >> name >> sex >> y >> m >> d;
            Node* temp = new Node(name, sex, y, m, d);
            int pd;
            in >> pd;
            if (pd == 1)
            {
                in >> name >> sex >> y >> m >> d;
                Person* tt = new Person(name, sex, y, m, d);
                temp->SetP2(tt);
            }
            else
                temp->SetP2(NULL);
            vv.push_back(temp);
        }
        root = vv[1];
        for (int i = 0; i < m; i++)
        {
            int a, b, c;
            a = v[0][i];
            b = v[1][i];
            c = v[2][i];
            vv[b]->Setparent(vv[a]);
            if (c == 0)
                vv[a]->Setleft(vv[b]);
            else
                vv[a]->Setright(vv[b]);
        }
    }
    Node* getRoot()
    {
        return root;
    }
    Node* find(string name)
    {
        return root->find(name);
    }
    void save(string path)
    {
        // 这么小的空间整一个甘泉算法实属大材小用
        // 树本质上是一个图,只要把所有点和所有边存下来就行了
        int n = 1;
        vector<int> v[3];
        queue<Node*> q;
        map<int, Node*> mp;
        // 广搜，给所有点编号
        q.push(root);
        mp[n] = root;
        while (!q.empty())
        {
            Node* temp = q.front();
            q.pop();
            if (temp->Getleft() != NULL)
            {
                n++;
                q.push(temp->Getleft());
                mp[n] = temp->Getleft();
            }
            if (temp->Getright() != NULL)
            {
                n++;
                q.push(temp->Getright());
                mp[n] = temp->Getright();
            }
        }
        // 存边
        for (int i = 1; i <= n; i++)
        {
            if (mp[i]->Getleft() != NULL)
            {
                v[0].push_back(i);
                for (int j = 1; j <= n; j++)
                {
                    if (mp[j] == mp[i]->Getleft())
                    {
                        v[1].push_back(j);
                        v[2].push_back(0);
                        break;
                    }
                }
            }
            if (mp[i]->Getright() != NULL)
            {
                v[0].push_back(i);
                for (int j = 1; j <= n; j++)
                {
                    if (mp[j] == mp[i]->Getright())
                    {
                        v[1].push_back(j);
                        v[2].push_back(1);
                        break;
                    }
                }
            }
        }
        // 存文件
        ofstream out(path);
        out << n << ' ' << v[0].size() << endl;
        for (int i = 0; i < v[0].size(); i++)
        {
            out << v[0][i] << " " << v[1][i] <<" "<<v[2][i]<< endl;
        }
        // 接下来n组数据，每组数据三行，第一行是节点信息，第二行是是否有配偶，第三行是配偶信息
        for (int i = 1; i <= n; i++)
        {
            Node* temp = mp[i];
            out << temp->Getname() << " " << temp->Getsex() << " " << temp->Getyear() << " " << temp->Getmonth() << " " << temp->Getday() << endl;
            if (temp->GetP2() != NULL)
            {
                out << "1" << endl;
                Person* tt = temp->GetP2();
                out << tt->Getname() << " " << tt->Getsex() << " " << tt->Getyear() << " " << tt->Getmonth() << " " << tt->Getday() << endl;
            }
            else
                out << "0" << endl;
        }
    }
    void travel(vector<Node*>* v)
    {
        root->travel(v);
    }
};

class Start
{
private:
    BTFG* Tree;
public:
    Node* selected;
    vector<Node*> bin;
    Start()
    {
        Tree = new BTFG;
        selected = Tree->getRoot();
    }
    ~Start()
    {
        for(int i=0;i<bin.size();i++)
            delete bin[i];
    }
    Node* getRoot()
    {
        return Tree->getRoot();
    }
    void AddB()
    {
        //selected->addbrother();
    }
    void AddC()
    {
        //selected->addchild();
    }
    void DP()
    {
        cout << *selected << endl;
    }
    void GetP()
    {
        Node* p = selected->Getparent();
        if (p != NULL)
            cout << *p << endl;
        else {}
        //cout << "无父母信息" << endl;
    }
    void DB()
    {
        //selected->displaybrother();
    }
    void DC()
    {
        //selected->displaychild();
    }
    vector<Node*>* DALL(vector<Node*>* v)
    {
        Node *t1=new Node("父母:",0,0,0,0);
        Node *t2=new Node("兄弟:",0,0,0,0);
        Node *t3=new Node("子女:",0,0,0,0);
        bin.push_back(t1);
        bin.push_back(t2);
        bin.push_back(t3);
        v->push_back(t1);
        v->push_back(selected->Getparent());
        v->push_back(t2);
        selected->displaybrother(v);
        v->push_back(t3);
        selected->displaychild(v);
        return v;
    }
    bool CHG(string name)
    {
        //cout << "请输入要切换的节点名称:";
        Node* temp = Tree->find(name);
        if (temp != NULL)
        {
            selected = temp;
            return true;
            //cout << "切换成功" << endl;
        }
        else    return false;
        //cout << "未找到该节点" << endl;
    }
    int COG()
    {
        int count = selected->Calgen();
        return count;
    }
    void SV(string path)
    {
        //cout << "请输入保存文件路径:";
        //cout << "正在保存文件" << endl;
        Tree->save(path);
    }
    void Load(string path)
    {
        //cout << "请输入存档的文件路径:";
        //cout << "正在导入文件" << endl;
        Tree = new BTFG(path);
        selected=Tree->getRoot();
        selected=selected;
    }
    void Op()
    {
        //SetConsoleOutputCP(CP_UTF8);
        //SetConsoleOutputCP(GB2312_CHARSET);

        //cout << "家谱树初始化完成" << endl;
        selected = Tree->getRoot();
        while (1)
        {
            char c;
            cin >> c;
            if (c == 1)         AddB();
            else if (c == 2)    AddC();
            else if (c == 3)    DP();
            else if (c == 4)    GetP();
            else if (c == 5)    DB();
            else if (c == 6)    DC();
            //else if (c == 7)    DALL();
            //else if (c == 8)    CHG();
            //else if (c == 9)    MF();
            else if (c == 10)   COG();
            //else if (c == 11)   SV();
            else if (c == 12)   break;
        }
    }
};

/*int main()
{
    Start T;
    string name = "ttt";
        Node * temp = new Node(name, 0, 0, 0, 0);
        vector<Node*>* v=new vector<Node*>;
    T.selected->addchild(temp);
    T.CHG(name);
    T.DALL(v);
}*/
